package cn.com.redenvelope;

import java.util.Random;

public abstract class AbstractRedEnvelopeCreator implements RedEnvelopeCreator{
	
	/**
	 * 产生红包金额
	 * @param totalMoney 红包总金额
	 * @param count 红包总个数
	 * @param type 红包产生类型：0=平均红包，1=随机金额红包
	 * @return
	 */
	protected int[] generateEnvelopeMoney(int totalMoney, int count, int type) {
		if ( totalMoney <= 0 || count <= 0 ) {
			//金额和数量必须都大于0
			return new int[] { -1 };
		}
		if (totalMoney < count) {
			//金额总数不可以小于红包数量
			return new int[] { -1 };
		}
		if (type == 0) {
			if (totalMoney % count != 0) {
				//总金额无法除尽数量，说明金额无法平分
				return new int[] { -1 };
			} else {
				return this.avgMoney(totalMoney, count);
			}
		} else if (type == 1){
			if (totalMoney >= count) {
				
				int[] initArr = this.randMoney(totalMoney, count);
				
				return this.randOrder(initArr);

			} else {
				//随机红包，金额不能小于数量，否则会分配金额失败
				return new int[] { -1 };
			}
		}
		
		return new int[] { -1 };
	}
	
	private int[] avgMoney(int totalMoney, int count) {
		int each = totalMoney / count ; 
		int[] result = new int[count];
		for (int i=0; i<count; i++) {
			result[i] = each;
		}
		return result;
	}
	
	private int[] randMoney(int totalMoney, int count) {
		Random rand = new Random();
		
		int temp = totalMoney;
		//算法，随机产生count个红包
		
		int remainNum=0, mod=0, each=1, ratio=1, leastRatio = 1;
		
		int[] result = new int[count];
		
		for( int i = 0, j; i < count; i++ ) {  
			
			if ( i == count - 1) {
				j = temp;
			} else {
				remainNum = count - i;
				mod = temp % remainNum;
				each = ( temp - mod ) / remainNum;
				ratio = rand.nextInt(remainNum - 1);
				
				ratio = ratio > 0 ? ratio : 1;
				
				if (remainNum <= 5) {
					leastRatio = remainNum - 1;
				} else {
					leastRatio = remainNum - (remainNum - remainNum % 5) / 5;
				}
				
				ratio = ratio > leastRatio ? ratio : leastRatio;
				
				j = rand.nextInt(temp - each * ratio);
				j = j == 0 ? 1 : j;
				if ( remainNum - temp + j - 1 > 0) {
					j = 1;
				}
				temp -= j;            
			}
			
			result[i] = j;
		}
		
		return result;
	}
	
	private int[] randOrder(int[] initArr) {
		Random rand = new Random();
		
		int swapIndex = 0, swap = 0;
		
		for( int index = initArr.length - 1; index >= 0; index-- ) {    
            
			if (index > 1) {
	            swapIndex = rand.nextInt(index - 1);
	            
	            swap = initArr[index];    
	            initArr[index] = initArr[swapIndex];    
	            initArr[swapIndex] = swap;  
			}

        } 
		
		return initArr;
	}
}
